﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YunSpace.Application.SystemManage;
using YunSpace.Core;
using YunSpace.Data;
using YunSpace.Domain.Entity.WorkFlow;
using YunSpace.Domain.IRepository.WorkFlow;
using YunSpace.Domain.ViewModel.WorkFlow;
using YunSpace.Repository.WorkFlow;

namespace YunSpace.Application.WorkFlow
{
    /// <summary>
    /// 流程管理
    /// </summary>
    public partial class FlowManageApp
    {
        private readonly IWorkFlowRepository _workFlowRepository = new WorkFlowRepository();
        private readonly IWorkFlowDetailRepository _workFlowDetailRepository = new WorkFlowDetailRepository();
        private readonly ItemsDetailApp _itemsDetailApp = new ItemsDetailApp();
        private readonly UserApp _userApp = new UserApp();
        private static readonly Dictionary<string, string> UserIdToNameMaps = new Dictionary<string, string>();
        private static readonly Dictionary<string, string> RoleIdToNameMaps = new Dictionary<string, string>();

        static FlowManageApp()
        {
            InitCacheData();
        }

        public bool AddWorkFlow(WorkFlowEntity workFlow)
        {
            var entity = _workFlowRepository.FindEntity(x =>
                x.F_WorkFormId == workFlow.F_WorkFormId && (x.F_DeleteMark == null || x.F_DeleteMark != true));

            if (entity != null)
            {
                return false;
            }

            workFlow.Create();
            _workFlowRepository.Insert(workFlow);
            return true;
        }

        public bool UpdateWorkFlow(WorkFlowEntity workFlow, string keyValue)
        {
            var entity = _workFlowRepository.FindEntity(x =>
                x.F_WorkFormId == workFlow.F_WorkFormId && x.F_Id != keyValue && (x.F_DeleteMark == null || x.F_DeleteMark != true));

            if (entity != null)
            {
                return false;
            }

            workFlow.Modify(keyValue);
            _workFlowRepository.Update(workFlow);
            return true;
        }

        public void DeleteWorkFlow(string keyValue)
        {
            var entity = _workFlowRepository.FindEntity(keyValue);
            entity.Remove();

            _workFlowRepository.Update(entity);
        }

        public WorkFlowEntity GetWorkFlow(string keyValue)
        {
            var entity = _workFlowRepository.FindEntity(keyValue);

            if (entity == null) return new WorkFlowEntity();

            if (entity.F_CreatorUserId != null)
            {
                var user = _userApp.GetForm(entity.F_CreatorUserId);
                entity.F_CreatorUserId = user.F_RealName;
            }

            if (entity.F_LastModifyUserId == null) return entity;

            var modifyUser = _userApp.GetForm(entity.F_LastModifyUserId);
            entity.F_LastModifyUserId = modifyUser.F_RealName;

            return entity;

        }

        public void DeleteWorkFlowDetail(string keyValue)
        {
            var entity = _workFlowDetailRepository.FindEntity(keyValue);
            entity.Remove();

            _workFlowDetailRepository.Update(entity);
        }

        /// <summary>
        /// 获取流程管理详情
        /// </summary>
        /// <param name="keyValue"></param>
        /// <returns></returns>
        public WorkFlowDetailEntity GetWorkFlowDetail(string keyValue)
        {
            return _workFlowDetailRepository.FindEntity(keyValue);
        }

        /// <summary>
        /// 获取流程管理列表
        /// </summary>
        /// <param name="pagination"></param>
        /// <returns></returns>
        public List<FlowManagerViewModel> GetFlowManages(Pagination pagination)
        {
            return ToFlowManagerViewModels(_workFlowRepository.GetFlowManages(pagination));

            List<FlowManagerViewModel> ToFlowManagerViewModels(IEnumerable<FlowManageDto> flowManages)
            {
                return flowManages.Select(ToFlowManagerViewModel).ToList();
            }

            FlowManagerViewModel ToFlowManagerViewModel(FlowManageDto flowManage)
            {
                var workForms = _itemsDetailApp.GetItemList("lcbd");

                var flowManageVM = new FlowManagerViewModel()
                {
                    F_WorkFlowId = flowManage.F_WorkFlowId,
                    F_Creator = flowManage.F_Creator,
                    F_CreatorTime = flowManage.F_CreatorTime,
                    F_WorkFlowDetailCount = flowManage.F_WorkFlowDetailCount,
                    F_WorkFlowName = flowManage.F_WorkFlowName,
                };

                if (workForms.Any(x => x.F_ItemCode == flowManage.F_WorkFormId))
                {
                    flowManageVM.F_WorkForm =
                        workForms.First(x => x.F_ItemCode == flowManage.F_WorkFormId).F_ItemName;
                }

                return flowManageVM;
            }
        }

        public void AddWorkFlowDetail(WorkFlowDetailEntity workFlowDetail)
        {
            workFlowDetail.Create();
            _workFlowDetailRepository.Insert(workFlowDetail);
        }

        public void UpdateFlowManageInfo(WorkFlowDetailEntity workFlowDetail, string keyValue)
        {
            var workFlowDetailEntity = _workFlowDetailRepository.FindEntity(keyValue);

            workFlowDetailEntity.F_WorkFlowNo = workFlowDetail.F_WorkFlowNo;
            workFlowDetailEntity.F_StepName = workFlowDetail.F_StepName;
            workFlowDetailEntity.F_TimeOutTip = workFlowDetail.F_TimeOutTip;
            workFlowDetailEntity.F_IsFishTime = workFlowDetail.F_IsFishTime;
            workFlowDetailEntity.F_WorkHours = workFlowDetail.F_WorkHours;
            workFlowDetailEntity.F_TimeOutOpreation = workFlowDetail.F_TimeOutOpreation;
            workFlowDetailEntity.F_OpreationType = workFlowDetail.F_OpreationType;
            workFlowDetailEntity.F_OpreationUserId = workFlowDetail.F_OpreationUserId;
            workFlowDetailEntity.F_OpreationStrategy = workFlowDetail.F_OpreationStrategy;
            workFlowDetailEntity.F_ReturnStrategy = workFlowDetail.F_ReturnStrategy;
            workFlowDetailEntity.F_ReturnType = workFlowDetail.F_ReturnType;
            workFlowDetailEntity.F_MessageSend = workFlowDetail.F_MessageSend;
            workFlowDetailEntity.F_CcUserId = workFlowDetail.F_CcUserId;

            workFlowDetailEntity.F_ConunTerisnUserId = workFlowDetail.F_ConunTerisnUserId;
            workFlowDetailEntity.F_IsCountersign = workFlowDetail.F_IsCountersign;
            workFlowDetailEntity.F_OperationPersonType = workFlowDetail.F_OperationPersonType;
            workFlowDetailEntity.F_CcOperationPType = workFlowDetail.F_CcOperationPType;
            workFlowDetailEntity.F_CounTersignType = workFlowDetail.F_CounTersignType;
            workFlowDetailEntity.F_CountersignNum = workFlowDetail.F_CountersignNum;

            workFlowDetailEntity.F_ApprovalNo = workFlowDetail.F_ApprovalNo;
            workFlowDetailEntity.Modify(keyValue);
            _workFlowDetailRepository.Update(workFlowDetailEntity);
        }

        /// <summary>
        /// 获取流程步骤列表
        /// </summary>
        /// <param name="pagination"></param>
        /// <param name="keyValue"></param>
        /// <returns></returns>
        public List<FlowManageStepViewModel> GetFlowManageSteps(Pagination pagination, string keyValue)
        {
            pagination.rows = _workFlowDetailRepository.IQueryable(x => x.F_WorkFlowId == keyValue && (x.F_DeleteMark == null || !x.F_DeleteMark.Value)).Count();
            return ToFlowManageStepViewModels(_workFlowDetailRepository.FindList(x => x.F_WorkFlowId == keyValue && (x.F_DeleteMark == null || !x.F_DeleteMark.Value), pagination).OrderBy(x => x.F_WorkFlowNo));

            List<FlowManageStepViewModel> ToFlowManageStepViewModels(IEnumerable<WorkFlowDetailEntity> workFlowDetails)
            {
                var timeOutTipItems = _itemsDetailApp.GetItemList("cqts");
                var timeOutOpreationItems = _itemsDetailApp.GetItemList("cscl");
                var opreationTypeItems = _itemsDetailApp.GetItemList("clfs");
                var opreationStrategyItems = _itemsDetailApp.GetItemList("clcl");
                var returnStrategyItems = _itemsDetailApp.GetItemList("thcl");
                var returnTypeItems = _itemsDetailApp.GetItemList("thlx");
                var messageSendItems = _itemsDetailApp.GetItemList("xxfsfs");
                var OperationPersonType = _itemsDetailApp.GetItemList("OperationPersonType");

                var userName = "";
                var roleName = "";
                return workFlowDetails.Select(entity => new FlowManageStepViewModel
                {
                    F_WorkFlowDetailId = entity.F_Id,
                    F_WorkFlowId = entity.F_WorkFlowId,
                    F_WorkFlowNo = entity.F_WorkFlowNo.ToString(),
                    F_StepName = entity.F_StepName,
                    F_WorkHours = entity.F_WorkHours == null ? "" : entity.F_WorkHours.ToString(),
                    F_OpreationUsers = entity.F_OpreationUserId==null?"":
                        entity.F_OperationPersonType=="1"? string.Join(",",(from userId in entity.F_OpreationUserId?.Split(new[] { ',' },
                                            StringSplitOptions.RemoveEmptyEntries) ?? new string[0]
                                            select (UserIdToNameMaps.TryGetValue(userId, out userName) ? userName : "")))
                         : string.Join(",", (from roleid in entity.F_OpreationUserId?.Split(new[] { ',' },
                                              StringSplitOptions.RemoveEmptyEntries) ?? new string[0]
                                             select (RoleIdToNameMaps.TryGetValue(roleid, out roleName) ? roleName : ""))),


                    F_TimeOutOpreation = entity.F_TimeOutOpreation == null
                        ? ""
                        : (timeOutOpreationItems.First(x => x.F_ItemCode == (entity.F_TimeOutOpreation).ToString()))
                        .F_ItemName,
                    F_ReturnStrategy = entity.F_ReturnStrategy == null
                        ? ""
                        : (returnStrategyItems.First(x => x.F_ItemCode == (entity.F_ReturnStrategy).ToString()))
                        .F_ItemName,
                    F_ReturnType = entity.F_ReturnType == null
                        ? ""
                        : (returnTypeItems.First(x => x.F_ItemCode == (entity.F_ReturnType).ToString())).F_ItemName,
                    F_OpreationStrategy = entity.F_OpreationStrategy == null
                        ? ""
                        : (opreationStrategyItems.First(
                            x => x.F_ItemCode == (entity.F_OpreationStrategy).ToString())).F_ItemName,
                    F_TimeOutTip = entity.F_TimeOutTip == null
                        ? ""
                        : (timeOutTipItems.First(x => x.F_ItemCode == (entity.F_TimeOutTip).ToString())).F_ItemName,
                    F_MessageSend = string.Join(",",
                        (from timeOutOpreation in entity.F_MessageSend?.Split(',') ?? new string[0]
                         where messageSendItems.Any(x => x.F_ItemCode == timeOutOpreation)
                         select (messageSendItems.First(x => x.F_ItemCode == timeOutOpreation).F_ItemName))),
                    F_OpreationTypes = string.Join(",",
                        (from opreationType in
                                entity.F_OpreationType?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) ??
                                new string[0]
                         where opreationTypeItems.Any(x => x.F_ItemCode == opreationType)
                         select opreationTypeItems.First(x => x.F_ItemCode == opreationType).F_ItemName)),
                    F_CcOperationPType= entity.F_CcOperationPType == null ? "" : (OperationPersonType.First(x => x.F_ItemCode == entity.F_CcOperationPType).F_ItemName),
                    F_CcUserId = string.Join(",",
                        (from ccUserId in entity.F_CcUserId?.Split(new[] { ',' },
                                              StringSplitOptions.RemoveEmptyEntries) ?? new string[0]
                         select (UserIdToNameMaps.TryGetValue(ccUserId, out userName) ? userName : ""))),
                    F_OperationPersonType= entity.F_OperationPersonType == null ? "" : (OperationPersonType.First(x => x.F_ItemCode == entity.F_OperationPersonType).F_ItemName),                    
                    F_IsCountersign=entity.F_IsCountersign,
                    F_CounTersignType=entity.F_CounTersignType == null ? "" : (OperationPersonType.First(x => x.F_ItemCode == entity.F_CounTersignType).F_ItemName)
                }).ToList();
            }
        }

        private static void InitCacheData()
        {
            var userApp = new UserApp();
            var users = userApp.GetUsers("");

            foreach (var user in users)
            {
                UserIdToNameMaps.Add(user.F_Id, user.F_RealName);
            }

            var roleApp = new RoleApp();
            var roles = roleApp.GetList();
            foreach (var role in roles) {
                RoleIdToNameMaps.Add(role.F_EnCode,role.F_FullName);
            }
        }
    }
}
